from functools import lru_cache
import logging
import json
from datetime import datetime
from opentelemetry import trace
from logging.handlers import TimedRotatingFileHandler

from pydantic import BaseModel, Field

_log_path = "/var/log/app"

class LogConf(BaseModel):
    path: str = Field(alias="Path")

class GoZeroFormatter(logging.Formatter):
    def format(self, record):
        tracer = trace.get_current_span()
        trace_id = tracer.get_span_context().trace_id if tracer else ""
        span_id = tracer.get_span_context().span_id if tracer else ""
        
        log_data = {
            "@timestamp": datetime.now().astimezone().isoformat(),
            "caller": f"{record.pathname}:{record.lineno}",
            "content": record.getMessage(),
            "level": record.levelname.lower(),
            "span": f"{span_id:x}" if span_id else "",
            "trace": f"{trace_id:x}" if trace_id else "",
        }
        
        if hasattr(record, 'duration'):
            log_data['duration'] = f"{record.duration:.1f}ms"
            
        return json.dumps(log_data, ensure_ascii=False)

@lru_cache(maxsize=1)
def setup_logger(log_path):
    global _log_path
    if hasattr(setup_logger, "_initialized"):
        if log_path and log_path != _log_path:
            raise RuntimeError("Logger already initialized with different path")
        return logging.getLogger()
    
    _log_path = log_path
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    
    handler = TimedRotatingFileHandler(
        filename=f'{_log_path}/app.log',
        when='midnight',
        backupCount=7,
        encoding='utf-8'
    )
    
    handler.setFormatter(GoZeroFormatter())
    logger.addHandler(handler)
    
    setup_logger._initialized = True
    return logger

@lru_cache(maxsize=1)
def my_logger():
    global _log_path
    return setup_logger(_log_path)